<!-- 监测点树 -->

<template>
  <EasyTree v-model="model" v-bind="treeProps" :key="param.statisticType" @idChange="emitChange">
    <template #default="{ data, nodeClass }">
      <slot name="node" :data="data" :nodeClass="nodeClass" />
    </template>
  </EasyTree>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import props from './props'

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name: 'PointTree',

  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [
    CORE.mixWeb(),
    CORE.mixTree('point', 'point_'),
    CORE.mixTree('category', 'category_'),
  ],

  /**
   * 属性注册 (抽取以便查阅)
   */
  props,

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return {
      model: undefined, // 内部绑定值
      EMPTY: undefined, // 空值常量
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 前缀
     */
    PRE() {
      const { statisticType } = this.param
      return statisticType === 5 ? 'point_' : 'category_'
    },

    /**
     * 结构树属性
     */
    treeProps() {
      const { PRE, GETTER } = this

      return {
        tree: this[`${PRE}tree`],
        field: this[`${PRE}TREE_FIELD`],
        filterTip: `${GETTER.category}名称`,
      }
    },

    /**
     * 结构树映射
     */
    treeMap() {
      return this[`${this.PRE}treeMap`]
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: {
    /**
     * 监听所属对象
     */
    param: {
      deep: true,
      immediate: true,
      handler() {
        const { isDiff, setModel, emitChange } = this
        if (isDiff()) {
          setModel()
          emitChange()
        }
      },
    },
  },

  /**
   * 创建完成 (先抽取再调用)
   */
  created() {
    const { param, bind, $set } = this
    if (!Object.keys(param || {}).includes(bind)) $set(param, bind, '')
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 是否不等 (可覆盖)
     */
    isDiff() {
      const { param, bind, model } = this
      // 判断是否有值
      if (param[bind]) return param[bind] !== model
      else return model
    },

    /**
     * 设置内部绑定值 (可覆盖)
     */
    setModel() {
      const { param, bind, EMPTY } = this
      this.model = param[bind] || EMPTY
    },

    /**
     * 获取最终回传值 (可覆盖)
     */
    getValue() {
      const { model } = this
      return model
    },

    /**
     * 是否相等 (可覆盖)
     */
    equals(value) {
      const { param, bind } = this
      return param[bind] === value
    },

    /**
     * 提交改变 (可覆盖)
     */
    emitChange() {
      const { getValue, equals, param, bind, treeMap } = this

      // 获取新值
      const value = getValue()

      // 判断改变
      if (equals(value)) return

      // 更新绑定
      this.$set(param, bind, value)
      this.$emit('change', treeMap[value] || {})
    },

    /**
     * 点击展开
     */
    toExpand(data) {
      this.$emit('expand', data)
    },

    /**
     * 点击收缩
     */
    toCollapse(data) {
      this.$emit('collapse', data)
    },
  },
}
</script>
